package uk.gov.swmprobation.cpvisibility;

import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

public class LocationServices {

	private static final int TWO_MINUTES = 1000 * 60 * 2;
	public static final int FEW_MINUTES = 1000 * 60 * 10;
	
	private static long locationTime;
	private static double locationLat =0;
	private static double locationLng =0;
	private static float locationAccuracy;
	
	Context mContext;
	static LocationManager lm;
	static LocationListener locationListener;
	
	public LocationServices(Context mContext) {
		this.mContext = mContext;
	}
	
	public void GetLastLocation(){
		LocationManager lm = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
        Location l = null;
        
        Location networkLocation = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        Location gpsLocation = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        
        if (networkLocation != null && gpsLocation != null){
        	if(gpsLocation.getTime()<networkLocation.getTime()-TWO_MINUTES){
        		l=networkLocation;
        	} else {
        		l=gpsLocation;
        	}
        } else if(gpsLocation != null){
        	l=gpsLocation;
        } else {
        	l=networkLocation;
        }

        if(l != null){
        	if (System.currentTimeMillis()-l.getTime()<FEW_MINUTES){
        		locationLat = l.getLatitude();
    			locationLng = l.getLongitude();
				locationLng = l.getLongitude();
				locationAccuracy = l.getAccuracy();
        	} else {
        		Log.e("LS","location data old");
        	}
        } else {
        	Log.e("LS","location null");
        }
	}
	
	public void GetALocation(){
		lm = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
		Criteria crit = new Criteria();
		crit.setAccuracy(Criteria.ACCURACY_FINE);
		Boolean provider_found = false;
		
		locationListener = new MyLocationListener();
		  
		if (lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
			lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
			provider_found = true;
		}
			
		if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)){
			lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
			provider_found = true;
		}
		
		if(!provider_found) {
			Toast.makeText(mContext, "Location can not be found, please check settings", Toast.LENGTH_SHORT).show();
			return;
		}
	}
	public static void stopListener(){
		if(locationListener==null) return;
		lm.removeUpdates(locationListener);
	}
	
	public static boolean locationAvailable(){
		if (locationLat==0 && locationLng==0){
			return false;
		}
		if (System.currentTimeMillis() - locationTime > FEW_MINUTES){
			return false;
		}
		return true;
	}
	
	public static long getLocationTime(){
		return locationTime;
	}
	
	public static void setLocationTime(long time){
		locationTime = time;
	}
	
	public static double getLocationLat(){
		return locationLat;
	}

	public static void setLocationLat(double lat){
		locationLat = lat;
	}
	
	public static double getLocationLng(){
		return locationLng;
	}
	
	public static void setLocationLng(double lng){
		locationLng = lng;
	}
	
	private boolean betterLocation(Location location){
		
		if (!locationAvailable()) {
			return true;
	    }
		
		long timeDelta = location.getTime() - locationTime;
	    boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
	    
	    if (isSignificantlyNewer) {
	    	return true;
	    }
	    
	    boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
	    
	    if (isSignificantlyOlder) {
	    	return false;
	    }
	    
	    boolean isNewer = timeDelta > 0;

	    int accuracyDelta = (int) (location.getAccuracy() - locationAccuracy);
	    boolean isLessAccurate = accuracyDelta > 0;
	    boolean isMoreAccurate = accuracyDelta < 0;   
	    
	    if (isMoreAccurate) {
	    	return true;
	    } else if (isNewer && !isLessAccurate) {
	    	return true;
	    }

	    return false;
		
	}
	
	private class MyLocationListener implements LocationListener {
		public void onLocationChanged(Location location) {
		      if(betterLocation(location)){
					locationTime = location.getTime();
					locationLat = location.getLatitude();
					locationLng = location.getLongitude();
					locationAccuracy = location.getAccuracy();
					String locationProvider = location.getProvider();
					if (locationProvider.equals(LocationManager.GPS_PROVIDER)){
						stopListener();
					}
					MainActivity.enabledButtons(true);
				}
		    }

		    public void onStatusChanged(String provider, int status, Bundle extras) {}

		    public void onProviderEnabled(String provider) {}

		    public void onProviderDisabled(String provider) {}
	}
	
}
